import 'dart:async';

import 'package:aichat_flutter_wallet/module_common/network/web3_js_call.dart';
import 'package:lib_util/log/log.dart';
import 'package:lib_util/utils/utils.dart';

import 'chaincore.dart';

class TronChain extends ChainCore {
  TronChain._privateConstructor();

  static final TronChain _instance = TronChain._privateConstructor();

  factory TronChain() {
    return _instance;
  }

  Future<String> signMessage(String pk, String message) async {
    if (!await localAuth()) {
      return Future.error('Authentication failed');
    }
    Completer<String> completer = Completer();
    return generateFuture(
        Web3JsCall()
            .jsTronSignMessage(pk, message, generateCallback(completer)),
        completer);
  }

  Future<Map<String, dynamic>> buildSendTokenTransaction(
      {required String type,
      required String from,
      required String to,
      required String token,
      required String amount,
      String? tokenId}) {
    Completer<Map<String, dynamic>> completer = Completer();
    return generateFuture(
        Web3JsCall().jsTronBuildSendTokenTransaction(
            type: type,
            from: from,
            to: to,
            token: token,
            amount: amount,
            tokenId: tokenId,
            callback: JsCallback(
                showError: false,
                callback: (result) {
                  completer.complete(result);
                },
                errorCallback: (error) {
                  completer.completeError(error);
                })),
        completer);
  }

  Future<TronTransaction> buildOmpBridgeTransaction({
    required String rpc,
    required String contract,
    required String fromAddress,
    required String crossAddress,
    required String amount,
  }) {
    Completer<TronTransaction> completer = Completer();

    return generateFuture(
        Web3JsCall().jsTronBuildOmpBridgeTransaction(
            rpc: rpc,
            contract: contract,
            fromAddress: fromAddress,
            crossAddress: crossAddress,
            amount: amount,
            callback: JsCallback(callback: (result) {
              completer.complete(
                  TronTransaction.fromJson(result as Map<String, dynamic>));
            }, errorCallback: (error) {
              completer.completeError(error);
            })),
        completer);
  }

  Future<String> sendTransaction(
      {required String pk,
      required String transaction,
      bool waitForReceipt = false}) async {
    Completer<String> completer = Completer();
    return generateFuture(
        Web3JsCall().jsTronSendTransaction(
            pk: pk,
            transaction: transaction,
            callback: generateCallback(completer),
            waitForReceipt: waitForReceipt),
        completer,
        timeoutSeconds: 100);
  }
}

class TronTransaction {
  bool? visible;
  String? txID;
  Map<String, dynamic>? raw_data;
  String? raw_data_hex;
  String? energy_used;

  String get from => Utils.convertEthereumAddressFromHexToBase58(
      _getParameterValue()['owner_address']);

  String get to => Utils.convertEthereumAddressFromHexToBase58(
      _getParameterValue()['contract_address']);

  TronTransaction.fromJson(Map<String, dynamic> json) {
    visible = json['visible'];
    txID = json['txID'];
    raw_data = json['raw_data'];
    raw_data_hex = json['raw_data_hex'];
    energy_used = json['energy_used'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> result = <String, dynamic>{};
    result['visible'] = visible;
    result['txID'] = txID;
    result['raw_data'] = raw_data;
    result['raw_data_hex'] = raw_data_hex;
    result['energy_used'] = energy_used;
    return result;
  }

  Map<String, dynamic> _getParameterValue() {
    return (((raw_data!['contract'] as List)[0]
        as Map<String, dynamic>)['parameter'] as Map<String, dynamic>)['value'];
  }

  String getMethods() {
    String methods = '';

    try {
      methods = _getParameterValue()['data'];

      methods = '0x${methods.substring(0, 8)}';
    } catch (e) {
      Log().e(e);
    }

    switch (methods) {
      case '0xa9059cbb':
        return TransactionFunc.transfer.name;
      case '0x095ea7b3':
        return TransactionFunc.approve.name;
      case '0xa22cb465':
        return TransactionFunc.setApproveForAll.name;
      default:
        return methods;
    }
  }
}
